package com.qianfeng.iot.gateway.config;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.qianfeng.iot.gateway.filters.AuthenGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

/**
 * Created by Jackiechan on 2022/7/19 14:38
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Configuration
public class GatewayConfig {
    /**
     * 通过用户的请求地址来进行限流的区分
     *
     * @return
     */
    @Bean
    public KeyResolver keyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
    }


    @Bean
    public RedisRateLimiter redisRateLimiter() {
        return new RedisRateLimiter(1, 1, 1);
    }

    /**
     * @param builder
     * @param keyResolver      用于区分每个请求是谁的
     * @param redisRateLimiter 限流的规则,限制每秒每个用户请求多少次
     * @return
     */
    @Bean
    public RouteLocator route(RouteLocatorBuilder builder, KeyResolver keyResolver, RedisRateLimiter redisRateLimiter, AuthenGatewayFilterFactory authenGatewayFilterFactory) {
      return   builder.routes()
                //这是令牌的
                .route("tokenroute", predicateSpec -> {
                    return predicateSpec.path("/api/v1/user/login")//设置断言,也就是匹配什么路径的请求会转发到当前的路由
                            .filters(gatewayFilterSpec -> {//设置过滤器
                                return gatewayFilterSpec.stripPrefix(2)//设置跳过地址中的前面两层路径
                                        .requestRateLimiter(config -> {//设置限流的规则
                                            config.setKeyResolver(keyResolver)//设置限流的判断标准
                                                    .setRateLimiter(redisRateLimiter);//设置限流的具体的次数
                                        });
                            }).uri("lb://iot-auth");//当前请求转发到哪个服务
                })
              .route("userroute", predicateSpec -> {
                  return predicateSpec.path("/api/v1/user/**")//设置断言,也就是匹配什么路径的请求会转发到当前的路由
                          .filters(gatewayFilterSpec -> {//设置过滤器
                              return gatewayFilterSpec.stripPrefix(2)//设置跳过地址中的前面两层路径
                                      .filter(authenGatewayFilterFactory.apply(new AuthenGatewayFilterFactory.Config()))
                                      .requestRateLimiter(config -> {//设置限流的规则
                                          config.setKeyResolver(keyResolver)//设置限流的判断标准
                                                  .setRateLimiter(redisRateLimiter);//设置限流的具体的次数
                                      });
                          }).uri("lb://iot-auth");//当前请求转发到哪个服务
              })
                //设置租户的拦截
                .route("tenantRoute", predicateSpec -> {
                    return predicateSpec.path("/api/v1/tenant/**")
                            .filters(gatewayFilterSpec -> {
                                return gatewayFilterSpec.stripPrefix(2).filter(authenGatewayFilterFactory.apply(new AuthenGatewayFilterFactory.Config()))
                                        .requestRateLimiter(config -> {
                                            config.setKeyResolver(keyResolver).setRateLimiter(redisRateLimiter);
                                        });
                            }).uri("lb://iot-tenant");

                })
                .build();

//                new Function<PredicateSpec, Buildable<Route>>() {
//            @Override
//            public Buildable<Route> apply(PredicateSpec predicateSpec) {
//                return predicateSpec.path("/api/v1/token/**").filters(new Function<GatewayFilterSpec, UriSpec>() {
//                    @Override
//                    public UriSpec apply(GatewayFilterSpec gatewayFilterSpec) {
//                        gatewayFilterSpec.stripPrefix(2).requestRateLimiter(new Consumer<RequestRateLimiterGatewayFilterFactory.Config>() {
//                            @Override
//                            public void accept(RequestRateLimiterGatewayFilterFactory.Config config) {
//                                config.setKeyResolver(keyResolver).setRateLimiter(redisRateLimiter)
//                            }
//                        });
//                    }
//                }).uri("lb://iot-auth");
//            }
//        }

    }

}